/**
 * @file lang_utils.h
 *
 * Language utilities
 *
 * @author Dahua Lin
 */

#ifdef _MSC_VER
#pragma once
#endif

#ifndef SLIPP_LANG_UTILS_H_
#define SLIPP_LANG_UTILS_H_

#include <type_traits>

namespace sli
{
	/**
	 * means no type is there
	 */
	struct nil_type { };

	/**
	 * The base class to make sure its derived classes are non-copyable
	 */
	class noncopyable
	{
	protected:
		noncopyable() { }
		~noncopyable() { }

	private:
		noncopyable(const noncopyable& );
		noncopyable& operator= (const noncopyable& );
	};


	/**
	 * A compile time size constant
	 */
	template<size_t N>
	struct size_constant
	{
		static const size_t value = N;
	};


	// enable_if

	using std::enable_if;

	/**
	 * lazy enable_if
	 */
	template<bool Cond, class TypeHost>
	struct lazy_enable_if
	{
		typedef typename TypeHost::type type;
	};

	template<class TypeHost>
	struct lazy_enable_if<false, TypeHost>
	{
	};


	// useful type traits

	using std::is_same;
	using std::is_pod;

	using std::is_pointer;
	using std::is_reference;
	using std::is_const;
	using std::is_convertible;

	using std::is_floating_point;
	using std::is_integral;
	using std::is_arithmetic;

}


// useful macros

/**
 * alignment
 */
#if SLIPP_PLATFORM_INTERFACE == SLIPP_WINDOWS_INTERFACE
#define SLIPP_ALIGN(a) __declspec(align(a))
#elif SLIPP_PLATFORM_INTERFACE == SLIPP_POSIX_INTERFACE
#define SLIPP_ALIGN(a) __attribute__((aligned(a)))
#endif

/**
 * strong inline
 */
#if SLIPP_PLATFORM_INTERFACE == SLIPP_WINDOWS_INTERFACE
#define SLIPP_ENSURE_INLINE __forceinline
#elif SLIPP_PLATFORM_INTERFACE == SLIPP_POSIX_INTERFACE
#define SLIPP_ENSURE_INLINE __attribute__((always_inline))
#endif


#endif


